#include "biplTypes.h"
#include <iostream>
#include <sstream>

/// implicitly convert to bool
intTypes::operator bool() const
{
	if (val == 0)
		return false;
	else
		return true;
}

/// implicitly convert to other types
intTypes::operator const floatTypes() const
{
	return toFloat();
}

intTypes::operator const degreeTypes() const
{
	return toDegree();
}

intTypes::operator const pairTypes() const	
{
	return toPair();
}

intTypes::operator const stringTypes() const
{
	return toString();
}

/// output stream operator
std::ostream&
	operator<<(std::ostream&out, const intTypes& s)
{
	out << s.val;
	return out;
}

/// Negation Operator
intTypes operator- (const intTypes &s)
{
	return intTypes(-s.val);
}

/// Arithmetic Operators
const intTypes operator+(const intTypes& lhs, const intTypes& rhs)
{
	return intTypes(lhs.val + rhs.val);
}

const intTypes operator-(const intTypes& lhs, const intTypes& rhs)
{
	return intTypes(lhs.val - rhs.val);
}

const intTypes operator/(const intTypes& lhs, const intTypes& rhs)
{
	return intTypes(lhs.val / rhs.val);
}

const intTypes operator*(const intTypes& lhs, const intTypes& rhs)
{
	return intTypes(lhs.val * rhs.val);
}

const intTypes operator%(const intTypes& lhs, const intTypes& rhs)
{
	return intTypes(lhs.val % rhs.val);
}

/// Arithmetic Assignment Operators
intTypes& operator+=(intTypes& lhs, const intTypes& rhs)
{
	lhs.val += rhs.val;
	return lhs;
}

intTypes& operator-=(intTypes& lhs, const intTypes& rhs)
{
	lhs.val -= rhs.val;
	return lhs;
}

intTypes& operator*=(intTypes& lhs, const intTypes& rhs)
{
	lhs.val *= rhs.val;
	return lhs;
}

intTypes& operator/=(intTypes& lhs, const intTypes& rhs)
{
	lhs.val /= rhs.val;
	return lhs;
}

intTypes& operator%=(intTypes& lhs, const intTypes& rhs)
{
	lhs.val %= rhs.val;
	return lhs;
}

/// Equality Operators
boolTypes operator==(const boolTypes& left, const intTypes& right)
{
	return boolTypes(left == right.toBoolean());
}

boolTypes operator!=(const boolTypes& left, const intTypes& right)
{
	return boolTypes(left != right.toBoolean());
}

boolTypes operator==(const intTypes& left, const boolTypes& right)
{
	return boolTypes(left.toBoolean() == right);
}

boolTypes operator!=(const intTypes& left, const boolTypes& right)
{
	return boolTypes(left.toBoolean() != right);
}

boolTypes operator==(const intTypes& left, const intTypes& right)
{
	return boolTypes(left.val == right.val);
}

boolTypes operator!=(const intTypes& left, const intTypes& right)
{
	return boolTypes(left.val != right.val);
}

/// Relational Operators
boolTypes operator<(const intTypes& left, const intTypes& right)
{
	return boolTypes(left.val < right.val);
}

boolTypes operator>(const intTypes& left, const intTypes& right)
{
	return boolTypes(left.val > right.val);
}

boolTypes operator<=(const intTypes& left, const intTypes& right)
{
	return boolTypes(left.val <= right.val);
}

boolTypes operator>=(const intTypes& left, const intTypes& right)
{
	return boolTypes(left.val >= right.val);
}

/// Logical Operators
boolTypes operator!(const intTypes& s)
{
	return !s.toBoolean();
}

boolTypes operator&&(const intTypes& left, const intTypes& right)
{
	return left.toBoolean() && right.toBoolean();
}

boolTypes operator||(const intTypes& left, const intTypes& right)
{
	return left.toBoolean() || right.toBoolean();
}

/// Type conversion functions
boolTypes intTypes::toBoolean() const
{
	if (val)
		return boolTypes(true);
	else
		return boolTypes(false);
}

intTypes intTypes::toInteger() const
{
	return intTypes(val);
}

floatTypes intTypes::toFloat() const
{
	return floatTypes(float(val));
}

degreeTypes intTypes::toDegree() const
{
	return degreeTypes(float(val));
}

pairTypes intTypes::toPair() const
{
	return pairTypes(float(val), float(val));
}

stringTypes intTypes::toString() const
{
	std::stringstream ss(std::stringstream::in | std::stringstream::out);
	ss << val;
	
	return stringTypes(ss.str());
}